package testcase.iotest;

import card.Card;
import card.Cardset;
import io.IIO;
import io.command.*;
import io.command.result.*;
import junit.framework.TestCase;

public class IOCommandTest extends TestCase {

	class IOStub implements IIO {
		public String lastPrint;

		private String[] input;
		private int inputCount;

		public IOStub() {

		}

		public IOStub(String[] input) {
			this.input = input;
			inputCount = 0;
		}

		@Override
		public String getNextInput() {
			return input[inputCount++];
		}

		@Override
		public void println() {
		}

		@Override
		public void println(String s) {
			lastPrint = s;
		}

		@Override
		public void print(String s) {
			lastPrint = s;
		}

		@Override
		public void print(Card c, int index) {
		}

		@Override
		public void print(Cardset cs) {
		}
	}

	public void testCardInputCommand() {
		// test invalid input (non-num) follows by valid input
		String input[] = new String[2];
		input[0] = "s";
		input[1] = "1";

		Cardset cards = new Cardset(3);
		Card card1 = new Card('d', '3');
		Card card2 = new Card('d', '2');
		cards.add(card1);
		cards.add(card2);

		IOStub io = new IOStub(input);

		CardInputCommand command = new CardInputCommand(io, cards);
		IOIntResult ioresult = (IOIntResult) command.execute();
		assertEquals("Fail input", io.lastPrint);
		assertEquals(1, ioresult.getResult());

		// test invalid input (out of cards bound) follows by valid input
		input = new String[2];
		input[0] = "3";
		input[1] = "0";
		io = new IOStub(input);
		command = new CardInputCommand(io, cards);

		ioresult = (IOIntResult) command.execute();
		assertEquals("Fail input", io.lastPrint);
		assertEquals(0, ioresult.getResult());

		// test valid input
		input = new String[2];
		input[0] = "1";
		io = new IOStub(input);
		command = new CardInputCommand(io, cards);

		ioresult = (IOIntResult) command.execute();
		assertEquals(null, io.lastPrint);
		assertEquals(1, ioresult.getResult());

	}

	public void testConfirmPlayCommand() {
		Cardset cards = new Cardset(3);
		Card card1 = new Card('d', '3');
		Card card2 = new Card('d', '2');
		cards.add(card1);
		cards.add(card2);

		// test invalid input follows by valid input
		String[] input = new String[2];
		input[0] = "3";
		input[1] = "c";
		IOStub io = new IOStub(input);
		ConfirmPlayCommand command = new ConfirmPlayCommand(io, cards);

		IOCharResult ioresult = (IOCharResult) command.execute();
		assertEquals('c', ioresult.getResult());

		// test valid input
		input = new String[2];
		input[0] = "r";
		io = new IOStub(input);
		command = new ConfirmPlayCommand(io, cards);

		ioresult = (IOCharResult) command.execute();
		assertEquals('r', ioresult.getResult());
	}

	public void testContinueGameCommand() {
		// test invalid input follows by valid input
		String[] input = new String[2];
		input[0] = "k";
		input[1] = "y";
		IOStub io = new IOStub(input);
		ContinueGameCommand command = new ContinueGameCommand(io, "test");

		IOCharResult ioresult = (IOCharResult) command.execute();
		assertEquals('y', ioresult.getResult());

		// test valid input
		input = new String[2];
		input[0] = "n";
		io = new IOStub(input);
		command = new ContinueGameCommand(io, "test");

		ioresult = (IOCharResult) command.execute();
		assertEquals('n', ioresult.getResult());
	}

	public void testPlayerLandlordRatingCommand() {
		Cardset cards = new Cardset(3);
		Card card1 = new Card('d', '3');
		Card card2 = new Card('d', '2');
		cards.add(card1);
		cards.add(card2);

		// test invalid input follows by valid input
		String[] input = new String[2];
		input[0] = "k";
		input[1] = "1";
		IOStub io = new IOStub(input);
		PlayerLandlordRatingCommand command = new PlayerLandlordRatingCommand(
				io, "test", cards);

		IOIntResult ioresult = (IOIntResult) command.execute();
		assertEquals(1, ioresult.getResult());

		// test valid input
		input = new String[2];
		input[0] = "2";
		io = new IOStub(input);
		command = new PlayerLandlordRatingCommand(io, "test", cards);

		ioresult = (IOIntResult) command.execute();
		assertEquals(2, ioresult.getResult());

	}

	public void testMessageCommands() {

		IOStub io = new IOStub();
		EndGameMessageCommand command1 = new EndGameMessageCommand(io);
		EndApplicationMessageCommand command2 = new EndApplicationMessageCommand(
				io);
		HandDisplayCommand command3 = new HandDisplayCommand(io,
				new Cardset(3), "test");
		NewRoundMessageCommand command4 = new NewRoundMessageCommand(io, "test");
		NotBiggerPlayMessageCommand command5 = new NotBiggerPlayMessageCommand(
				io);

		boolean succeed = true;

		try {
			command1.execute();
			command2.execute();
			command3.execute();
			command4.execute();
			command5.execute();
		} catch (Exception c) {
			succeed = false;
		}

		assertEquals(true, succeed);
	}
}
